using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Configuration.Provider;
using System.Web.Configuration;
using System.Web;
using BlogEngine.Core;

namespace BlogEngine.Core.Providers
{
	/// <summary>
	/// The proxy class for communication between
	/// the business objects and the providers.
	/// </summary>
	public static class BlogService
	{
		#region Provider model

		private static BlogProvider _provider;
		private static BlogProviderCollection _providers;
		private static object _lock = new object();

		/// <summary>
		/// Gets the current provider.
		/// </summary>
		public static BlogProvider Provider
		{
			get { return _provider; }
		}

		/// <summary>
		/// Gets a collection of all registered providers.
		/// </summary>
		public static BlogProviderCollection Providers
		{
			get { return _providers; }
		}

		/// <summary>
		/// Load the providers from the web.config.
		/// </summary>
		private static void LoadProviders()
		{
			// Avoid claiming lock if providers are already loaded
			if (_provider == null)
			{
				lock (_lock)
				{
					// Do this again to make sure _provider is still null
					if (_provider == null)
					{
						// Get a reference to the <blogProvider> section
						BlogProviderSection section = (BlogProviderSection)WebConfigurationManager.GetSection("BlogEngine/blogProvider");

						// Load registered providers and point _provider
						// to the default provider
						_providers = new BlogProviderCollection();
						ProvidersHelper.InstantiateProviders(section.Providers, _providers, typeof(BlogProvider));
						_provider = _providers[section.DefaultProvider];

						if (_provider == null)
							throw new ProviderException("Unable to load default BlogProvider");
					}
				}
			}
		}

		#endregion

		#region Posts

		/// <summary>
		/// Returns a Post based on the specified id.
		/// </summary>
		public static Post SelectPost(int id)
		{
			LoadProviders();
			return _provider.SelectPost(id);
		}

		/// <summary>
		/// Returns a Post based on the specified slug.
		/// </summary>
		/// <param name="slug">The slug.</param>
		/// <returns></returns>
		public static Post SelectPost(string slug)
		{
			LoadProviders();
			return _provider.SelectPost(slug);
		}

		/// <summary>
		/// Counts the posts.
		/// </summary>
		/// <returns></returns>
		public static long CountPosts()
		{
			LoadProviders();
			return _provider.CountPosts();
		}

		/// <summary>
		/// Selects the posts.
		/// </summary>
		/// <param name="startIndex">The start index.</param>
		/// <param name="count">The count.</param>
		/// <returns></returns>
		public static List<Post> SelectPosts(int startIndex, int count)
		{
			LoadProviders();
			return _provider.SelectPosts(startIndex, count);
		}

		/// <summary>
		/// Selects the posts by term.
		/// </summary>
		/// <param name="type">The type.</param>
		/// <param name="slug">The slug.</param>
		/// <param name="startIndex">The start index.</param>
		/// <param name="count">The count.</param>
		/// <returns></returns>
		public static List<Post> SelectPostsByTerm(TermType type, string slug, int startIndex, int count)
		{
			LoadProviders();
			return _provider.SelectPostsByTerm(type, slug, startIndex, count);
		}

		/// <summary>
		/// Selects the posts by author.
		/// </summary>
		/// <param name="author">The author.</param>
		/// <param name="startIndex">The start index.</param>
		/// <param name="count">The count.</param>
		/// <returns></returns>
		public static List<Post> SelectPostsByAuthor(string author, int startIndex, int count)
		{
			LoadProviders();
			return _provider.SelectPostsByAuthor(author, startIndex, count);
		}

		/// <summary>
		/// Selects the posts by date.
		/// </summary>
		/// <param name="dateFrom">The date from.</param>
		/// <param name="dateTo">The date to.</param>
		/// <param name="startIndex">The start index.</param>
		/// <param name="count">The count.</param>
		/// <returns></returns>
		public static List<Post> SelectPostsByDate(DateTime dateFrom, DateTime dateTo, int startIndex, int count)
		{
			LoadProviders();
			return _provider.SelectPostsByDate(dateFrom, dateTo, startIndex, count);
		}

		/// <summary>
		/// Persists a new Post in the current provider.
		/// </summary>
		public static void InsertPost(Post post)
		{
			LoadProviders();
			_provider.InsertPost(post);
		}

		/// <summary>
		/// Updates an exsiting Post.
		/// </summary>
		public static void UpdatePost(Post post)
		{
			LoadProviders();
			_provider.UpdatePost(post);
		}

		/// <summary>
		/// Deletes the specified Post from the current provider.
		/// </summary>
		public static void DeletePost(Post post)
		{
			LoadProviders();
			_provider.DeletePost(post);
		}

		#endregion

		#region Attachment

		/// <summary>
		/// Selects the attachment.
		/// </summary>
		/// <param name="id">The id.</param>
		/// <returns></returns>
		public static Attachment SelectAttachment(int id)
		{
			LoadProviders();
			return _provider.SelectAttachment(id);
		}

		/// <summary>
		/// Selects the attachments.
		/// </summary>
		/// <param name="startIndex">The start index.</param>
		/// <param name="count">The count.</param>
		/// <returns></returns>
		public static List<Attachment> SelectAttachments(int startIndex, int count)
		{
			LoadProviders();
			return _provider.SelectAttachments(startIndex, count);
		}

		/// <summary>
		/// Counts the attachments.
		/// </summary>
		/// <returns></returns>
		public static long CountAttachments()
		{
			LoadProviders();
			return _provider.CountAttachments();
		}

		/// <summary>
		/// Inserts the attachment.
		/// </summary>
		/// <param name="attachment">The attachment.</param>
		public static void InsertAttachment(Attachment attachment)
		{
			LoadProviders();
			_provider.InsertAttachment(attachment);
		}

		/// <summary>
		/// Updates the attachment.
		/// </summary>
		/// <param name="attachment">The attachment.</param>
		public static void UpdateAttachment(Attachment attachment)
		{
			LoadProviders();
			_provider.UpdateAttachment(attachment);
		}

		/// <summary>
		/// Deletes the attachment.
		/// </summary>
		/// <param name="attachment">The attachment.</param>
		public static void DeleteAttachment(Attachment attachment)
		{
			LoadProviders();
			_provider.DeleteAttachment(attachment);
		}

		#endregion

		#region Comments

		/// <summary>
		/// Selects the comment.
		/// </summary>
		/// <param name="id">The id.</param>
		/// <returns></returns>
		public static Comment SelectComment(int id)
		{
			LoadProviders();
			return _provider.SelectComment(id);
		}

		/// <summary>
		/// Selects the comments by post.
		/// </summary>
		/// <param name="postId">The post id.</param>
		/// <returns></returns>
		public static List<Comment> SelectCommentsByPost(int postId)
		{
			LoadProviders();
			return _provider.SelectCommentsByPost(postId);
		}

		/// <summary>
		/// Inserts the comment.
		/// </summary>
		/// <param name="comment">The comment.</param>
		public static void InsertComment(Comment comment)
		{
			LoadProviders();
			_provider.InsertComment(comment);
		}

		/// <summary>
		/// Updates the comment.
		/// </summary>
		/// <param name="comment">The comment.</param>
		public static void UpdateComment(Comment comment)
		{
			LoadProviders();
			_provider.UpdateComment(comment);
		}

		/// <summary>
		/// Deletes the comment.
		/// </summary>
		/// <param name="comment">The comment.</param>
		public static void DeleteComment(Comment comment)
		{
			LoadProviders();
			_provider.DeleteComment(comment);
		}

		public static void ChangeAllCommentStatusByPost(int postId, CommentStatus fromStatus, CommentStatus toStatus)
		{
			LoadProviders();
			_provider.ChangeAllCommentStatusByPost(postId, fromStatus, toStatus);
		}

		#endregion

		#region Pages

		/// <summary>
		/// Returns a Post based on the specified id.
		/// </summary>
		public static Page SelectPage(int id)
		{
			LoadProviders();
			return _provider.SelectPage(id);
		}

		/// <summary>
		/// Returns a Post based on the specified slug.
		/// </summary>
		/// <param name="slug">The slug.</param>
		/// <returns></returns>
		public static Page SelectPage(string slug)
		{
			LoadProviders();
			return _provider.SelectPage(slug);
		}

		/// <summary>
		/// Persists a new Post in the current provider.
		/// </summary>
		public static void InsertPage(Page post)
		{
			LoadProviders();
			_provider.InsertPage(post);
		}

		/// <summary>
		/// Updates an exsiting Post.
		/// </summary>
		public static void UpdatePage(Page post)
		{
			LoadProviders();
			_provider.UpdatePage(post);
		}

		/// <summary>
		/// Deletes the specified Post from the current provider.
		/// </summary>
		public static void DeletePage(Page post)
		{
			LoadProviders();
			_provider.DeletePage(post);
		}

		public static List<Page> SelectPages()
		{
			LoadProviders();
			return _provider.SelectPages();
		}

		#endregion

		#region Terms

		/// <summary>
		/// Selects the term.
		/// </summary>
		/// <param name="type">The type.</param>
		/// <param name="slug">The slug.</param>
		/// <returns></returns>
		public static Term SelectTerm(TermType type, string slug)
		{
			LoadProviders();
			return _provider.SelectTerm(type, slug);
		}

		/// <summary>
		/// Selects the terms.
		/// </summary>
		/// <returns></returns>
		public static List<Term> SelectTerms()
		{
			LoadProviders();
			return _provider.SelectTerms();
		}

		/// <summary>
		/// Selects the terms by post.
		/// </summary>
		/// <param name="postId">The post id.</param>
		/// <returns></returns>
		public static List<Term> SelectTermsByPost(int postId)
		{
			LoadProviders();
			return _provider.SelectTermsByPost(postId);
		}

		#endregion

		#region Settings

		/// <summary>
		/// Loads the settings from the provider and returns
		/// them in a Dictionary<string, string> for the BlogSettings class to use.
		/// </summary>
		public static Dictionary<string, string> LoadSettings()
		{
			LoadProviders();
			return _provider.LoadSettings();
		}

		/// <summary>
		/// Save the settings to the current provider.
		/// </summary>
		public static void SaveSettings(Dictionary<string,string> settings)
		{
			LoadProviders();
			_provider.SaveSettings(settings);
		}

		#endregion

		#region Ping services

		/// <summary>
		/// Loads the ping services.
		/// </summary>
		public static List<string> LoadPingServices()
		{
			return null;
		}

		/// <summary>
		/// Saves the ping services.
		/// </summary>
		/// <param name="services">The services.</param>
		public static void SavePingServices(List<string> services)
		{
		}

		#endregion
	}
}